import base64
import requests
import json
import threading
import time
import cv2
import datetime
import pymysql
from playsound import playsound
from aip import AipSpeech

search = 0
title = ''


def get_access_key():
    host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=xx&client_id=xx&client_secret=xx'
    response = requests.get(host)
    token = json.loads(response.text)['access_token']
    return token


def read_img(imgpath):
    with open(imgpath, 'rb') as f:
        data = base64.b64encode(f.read())
        return data.decode('utf-8')


def face_score(data, token):
    request_url = "https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token={}".format(token)

    params = {
        "image": data,
        "image_type": "BASE64",
        "face_field": "age,beauty,gender"
    }
    params = json.dumps(params)

    headers = {'content-type': 'application/json'}
    res = requests.post(request_url, headers=headers, data=params)

    # print(res.text)
    result = json.loads(res.text)['result']['face_list'][0]
    d = {
        '人脸置信度': result['face_probability'],
        '年龄': result['age'],
        '性别': result['gender']['type'],
        '评分': str(result['beauty']) + '分'
    }
    print(d)
    # print(json.loads(res.text))

    # return d


# 人脸搜索
def face_search(data, token):
    request_url = "https://aip.baidubce.com/rest/2.0/face/v3/search"

    params = "{\"image\":\"" + data + "\",\"image_type\":\"BASE64\",\"group_id_list\":\"test\"}"
    access_token = token
    request_url = request_url + "?access_token=" + access_token
    headers = {'content-type': 'application/json'}
    response = requests.post(request_url, data=params, headers=headers)
    result = json.loads(response.text)
    # print(result)
    global title
    try:
        if result['result']:
            user_list = result['result']['user_list'][0]

            if user_list['score'] > 80:
                face_score(data, token)
                save_sql(user_list['user_id'])
                voice_synthesis(user_list['user_id'])

                print(user_list)
            else:
                print('未注册')

                title = 'Face information is not registered'
        else:
            print('未搜索到人脸')

            title = 'No face detected. Please try again'
    except KeyError:
        print('识别过快')

        title = 'The identification is too quick. Please wait a moment'


# 人脸质量检测
def face_quality(data, token):
    request_url = "https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token={}".format(token)

    params = {
        "image": data,
        "image_type": "BASE64",
        "face_field": "quality"
    }
    params = json.dumps(params)

    headers = {'content-type': 'application/json'}
    res = requests.post(request_url, headers=headers, data=params)

    result = json.loads(res.text)['result']['face_list'][0]['quality']
    # print(result)
    d = {
        'left_eye': result['occlusion']['left_eye'],  # <0.6
        'right_eye': result['occlusion']['right_eye'],  # <0.6
        'nose': result['occlusion']['nose'],  # <0.7
        'mouth': result['occlusion']['mouth'],  # <0.7
        'left_cheek': result['occlusion']['left_cheek'],  # <0.8
        'right_cheek': result['occlusion']['right_cheek'],  # <0.8
        'chin_contour': result['occlusion']['chin_contour'],  # <0.6
        'blur': result['blur'],  # <0.7
        'illumination': result['illumination'],  # >40
        'completeness': result['completeness'],  # 1,人脸都在屏幕
    }
    if d['left_eye'] < 0.6 and d['right_eye'] < 0.6 and d['nose'] < 0.7 and d['left_cheek'] < 0.8 and d[
        'mouth'] < 0.7 and d['right_cheek'] < 0.8 \
            and d['chin_contour'] < 0.6 and d['blur'] < 0.7 and d['illumination'] > 40 and d['completeness'] == 1:
        face_join(data, token)
    else:
        return '人脸质量不合格'


# 人脸入库
def face_join(data, token):
    pass


# 删除用户组
def del_group(token):
    request_url = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/group/delete"

    params = "{\"group_id\":\"m\"}"
    access_token = token
    request_url = request_url + "?access_token=" + access_token
    headers = {'content-type': 'application/json'}
    response = requests.post(request_url, data=params, headers=headers)
    if response:
        print(response.json())


# 主函数
def main():
    while True:
        global search

        if search == 0:
            continue
        print('开始')
        lock.acquire()

        token = get_access_key()
        img = read_img('test.jpg')
        face_search(img, token)

        search = 0

        lock.release()
        time.sleep(5)


def voice_synthesis(name):
    """ 你的 APPID AK SK """
    try:
        APP_ID = 'xxx'
        API_KEY = 'xxx'
        SECRET_KEY = 'xx '

        client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
        d = {'xx': 'xx'}
        n = d[name]
        s = n + '打卡成功'
        result = client.synthesis(s, 'zh', 1, {  # zh代表中文
            'vol': 5,
        })
        # 返回的是一个音频流，需要保存成mp3文件
        # 识别正确返回语音二进制 错误则返回dict 参照下面错误码
        t = datetime.datetime.now().strftime('%Y-%m-%d%H%M%S')
        t = str(t)
        if not isinstance(result, dict):
            with open('v/' + t + '.mp3', 'wb') as f:  # 创建mp3文件并具有写权限，用二进制的方式打开
                f.write(result)

        playsound('v/' + t + '.mp3')
    except:
        pass


def save_sql(user_id):
    global title
    conn = pymysql.connect(
        host="127.0.0.1",
        user='root',
        password="xx",
        database="xx",
        charset="utf8")

    # 得到一个可以执行SQL语句的光标对象
    cursor = conn.cursor()  # 执行完毕返回的结果集默认以元组显示


    # 定义要执行的SQL语句
    Time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    week = datetime.datetime.now().strftime('%A')
    Time += "   " + week

    # sql = 'select * from clock'
    sql = 'insert into clock values(\'' + user_id + '\',\'' + Time + '\')'


    cursor.execute(sql)
    conn.commit()
    title = user_id + '  clock in success  ' + Time


    # 关闭光标对象
    cursor.close()

    # 关闭数据库连接
    conn.close()


def video():
    cap = cv2.VideoCapture(0)

    face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
    color = (0, 0, 255)

    while True:
        ret, img = cap.read()

        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转换灰色
        dst = cv2.equalizeHist(gray)  # 均衡化处理

        # 调用识别人脸
        faceRects = face_cascade.detectMultiScale(dst, 1.3, 5)

        for faceRect in faceRects:  # 单独框出每一张人脸
            x, y, w, h = faceRect
            # print(faceRect)
            # 框出人脸q
            cv2.rectangle(img, (x, y), (x + h, y + w), color, 2)

            a = img[y:y + w, x:x + h]
            cv2.imwrite("test.jpg", a)
            global title
            cv2.putText(img, title, (0, 450), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1, 4)
            global search
            if search == 0:
                search = 1

        Time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        week = datetime.datetime.now().strftime('%A')

        Time += "   " + week
        cv2.putText(img, Time, (10, 20), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 255), 1, 4)
        cv2.namedWindow("image", 0)  # 0可调大小，注意：窗口名必须imshow里面的一窗口名一直
        cv2.resizeWindow("image", 800, 600)  # 设置长和宽
        cv2.imshow("image", img)  # 显示图像


        if cv2.waitKey(1) & 0xFF == ord('q'):
            break


    cap.release()

    cv2.destroyAllWindows()


if __name__ == '__main__':
    lock = threading.Lock()
    t1 = threading.Thread(target=video, args=())
    t2 = threading.Thread(target=main, args=())
    t1.start()
    t2.start()
